package repository

import (
	"bbs-web/internal/domain"
	"bbs-web/internal/repository/cache"
	"bbs-web/internal/repository/dao"
	"bbs-web/pkg/logger"
	"bbs-web/pkg/utils/zifo/slice"
	"context"
	"gorm.io/gorm"
)

type InteractiveRepo interface {
	Get(ctx context.Context, biz string, id int64) (domain.Interactive, error)
	Liked(ctx context.Context, biz string, id, uid int64) (bool, error)
	Collection(ctx context.Context, biz string, id, uid int64) (bool, error)
	IncrLiked(ctx context.Context, biz string, id, uid int64) error
	IncrDisLiked(ctx context.Context, biz string, id, uid int64) error
	IncrCollected(ctx context.Context, biz string, id, uid int64) error
	IncrDisCollected(ctx context.Context, biz string, id, uid int64) error
	GetCollectListByID(ctx context.Context, id int64, offset, limit int) ([]domain.Collect, error)
	CreateCollect(ctx context.Context, uid int64, cname string, desc string, isPub bool) (int64, error)
	IncrReadCnt(ctx context.Context, biz string, bizId int64) error
	BatchIncrReadCnt(ctx context.Context, biz []string, bizId []int64) error
	CollectEntity(ctx context.Context, biz string, uid, cid, bizId int64) error
}

type interactiveRepo struct {
	dao   dao.InteractiveDao
	cache cache.RedisInteractiveCache
	l     logger.Logger
}

func NewInteractiveRepo(dao dao.InteractiveDao, cache cache.RedisInteractiveCache, l logger.Logger) InteractiveRepo {
	return &interactiveRepo{dao: dao, cache: cache, l: l}
}

func (repo *interactiveRepo) CollectEntity(ctx context.Context, biz string, uid, cid, bizId int64) error {
	return repo.dao.InsertCollectInfo(ctx, biz, uid, cid, bizId)
}

func (repo *interactiveRepo) BatchIncrReadCnt(ctx context.Context, biz []string, bizId []int64) error {
	// 要不要检测 biz 和 bizId的长度是否相等
	err := repo.dao.BatchIncrReadCnt(ctx, biz, bizId)
	if err != nil {
		return err
	}
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题
	return repo.cache.IncrBatchReadCntIfPresent(ctx, biz, bizId)
}

func (repo *interactiveRepo) IncrReadCnt(ctx context.Context, biz string, bizId int64) error {
	//更新完数据库，状态和数量
	err := repo.dao.IncrReadCnt(ctx, biz, bizId)
	if err != nil {
		return err
	}
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题
	return repo.cache.IncrReadCntIfPresent(ctx, biz, bizId)
}

func (repo *interactiveRepo) CreateCollect(ctx context.Context, uid int64, cname string, desc string, isPub bool) (int64, error) {
	return repo.dao.InsertCollect(ctx, uid, cname, desc, isPub)
}

func (repo *interactiveRepo) GetCollectListByID(ctx context.Context, id int64, offset, limit int) ([]domain.Collect, error) {
	data, err := repo.dao.QueryCollectList(ctx, id, limit, offset)
	if err != nil {
		return nil, err
	}
	return slice.Map[dao.CollectionModle, domain.Collect](data, func(idx int, src dao.CollectionModle) domain.Collect {
		return repo.toDomainCollection(src)
	}), nil
}

func (repo *interactiveRepo) IncrLiked(ctx context.Context, biz string, id, uid int64) error {
	//更新完数据库，状态和数量
	err := repo.dao.IncrLiked(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题
	return repo.cache.IncrLikeCntIfPresent(ctx, biz, id)
}

func (repo *interactiveRepo) IncrDisLiked(ctx context.Context, biz string, id, uid int64) error {
	//更新完数据库，状态和数量
	err := repo.dao.IncrDisLiked(ctx, biz, id, uid)
	if err != nil {
		return err
	}
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题
	return repo.cache.IncrDisLikeCntIfPresent(ctx, biz, id)
}

func (repo *interactiveRepo) IncrCollected(ctx context.Context, biz string, id, uid int64) error {
	//更新完数据库，状态和数量
	return nil
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题

}

func (repo *interactiveRepo) IncrDisCollected(ctx context.Context, biz string, id, uid int64) error {
	//更新完数据库，状态和数量
	return nil
	//更新缓存的数量,使用lua脚本进行添加，对同一个键名多次进行修改，使用lua控制一次只有一个可以修改redis，避免并发问题

}

func (repo *interactiveRepo) toDomain(model dao.InteractiveModel) domain.Interactive {
	return domain.Interactive{
		ReadCnt:    model.ReadCnt,
		LikeCnt:    model.LikeCnt,
		CollectCnt: model.CollectCnt,
		CommentCnt: model.CommentCnt,
	}

}

func (repo *interactiveRepo) toDomainCollection(item dao.CollectionModle) domain.Collect {
	return domain.Collect{
		ID:          int64(item.ID),
		UserId:      item.UserId,
		CName:       item.CName,
		Description: item.Description,
		Sort:        item.Sort,
		ResourceNum: item.ResourceNum,
		IsPub:       item.IsPub,
		CommentNum:  item.CommentNum,
		CreateTime:  item.CreatedAt,
		UpdateTime:  item.UpdatedAt,
	}

}

func (repo *interactiveRepo) Get(ctx context.Context, biz string, id int64) (domain.Interactive, error) {
	//因为文章的点赞喜欢数量并发大，需要先从缓存查看
	data, err := repo.cache.Get(ctx, biz, id)
	if err != nil {
		return domain.Interactive{}, err
	}
	//实在没有在直接查询数据库
	da, err2 := repo.dao.Get(ctx, biz, id)
	if err2 != nil {
		return domain.Interactive{}, err2
	}
	//查完回写缓存
	data = repo.toDomain(da)
	err3 := repo.cache.Set(ctx, biz, id, data)
	if err3 != nil {
		return domain.Interactive{}, err3
	}
	return data, nil
}

func (repo *interactiveRepo) Liked(ctx context.Context, biz string, id, uid int64) (bool, error) {
	//查询业务用户行为表是否有记录，返回状态值
	_, err := repo.dao.GetLikedInfo(ctx, biz, id, uid)
	if err != nil {

	}
	switch err {
	case nil:
		return true, err
	case gorm.ErrRecordNotFound:
		return false, err
	default:
		return false, err
	}

}

func (repo *interactiveRepo) Collection(ctx context.Context, biz string, id, uid int64) (bool, error) {
	//查询业务用户行为表是否有记录，返回状态值
	_, err := repo.dao.GetCollectionInfo(ctx, biz, id, uid)
	if err != nil {

	}
	switch err {
	case nil:
		return true, err
	case gorm.ErrRecordNotFound:
		return false, err
	default:
		return false, err
	}

}
